package com.cskaoyan.user.service.impl;

import com.alibaba.fastjson.JSON;
import com.cskaoyan.mall.commons.exception.ExceptionProcessorUtils;
import com.cskaoyan.mall.commons.exception.ValidateException;
import com.cskaoyan.mall.commons.util.jwt.JwtTokenUtils;
import com.cskaoyan.user.constants.UserRetCode;
import com.cskaoyan.user.converter.UserConverterMapper;
import com.cskaoyan.user.dal.entitys.Member;
import com.cskaoyan.user.dal.entitys.UserVerify;
import com.cskaoyan.user.dal.persistence.MemberMapper;
import com.cskaoyan.user.dal.persistence.UserVerifyMapper;
import com.cskaoyan.user.dto.*;
import com.cskaoyan.user.properties.EmailProperties;
import com.cskaoyan.user.service.IUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.DigestUtils;
import tk.mybatis.mapper.entity.Example;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * @author yangzihui
 * @Description 用户模块的service
 * @Create 2022-07-08 20:02
 * @Version
 */
@Service
@Slf4j
@EnableConfigurationProperties(value = EmailProperties.class)
public class UserServiceImpl implements IUserService {

    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    private UserVerifyMapper userVerifyMapper;
    @Autowired
    private JavaMailSender mailSender;
    @Autowired
    private EmailProperties emailProperties;
    @Autowired
    private UserConverterMapper userConverterMapper;


    /**
     * 用户注册的方法
     *
     * @param userRegisterRequest
     * @return
     */
    @Override
    public UserRegisterResponse register(UserRegisterRequest userRegisterRequest) {
        UserRegisterResponse userRegisterResponse = new UserRegisterResponse();
        try {
            // 判断用户名和密码是否为空
            userRegisterRequest.requestCheck();
            // 判断email是否是合法的邮箱地址
            if (!userRegisterRequest.getEmail().matches("^[A-Za-z0-9\\u4e00-\\u9fa5]+@[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(?:\\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$")) {
                throw new ValidateException(UserRetCode.REQUEST_FORMAT_ILLEGAL.getCode(), UserRetCode.REQUEST_FORMAT_ILLEGAL.getMessage());
            }
            // 判断用户名是否重复
            validRegisterParameterRepeat("username", userRegisterRequest.getUserName());
            // 判断email是否重复
            validRegisterParameterRepeat("email", userRegisterRequest.getEmail());

            // 向用户表中插入一条记录
            Member member = new Member();
            member.setUsername(userRegisterRequest.getUserName());
            member.setEmail(userRegisterRequest.getEmail());
            // password要加密处理
            String md5DigestAsHex = DigestUtils.md5DigestAsHex(userRegisterRequest.getUserPwd().getBytes());
            member.setPassword(md5DigestAsHex);
            member.setCreated(new Date());
            member.setUpdated(new Date());
            member.setIsVerified("N");
            member.setState(1);

            int effectRows = memberMapper.insert(member);
            if (effectRows != 1) {
                userRegisterResponse.setCode(UserRetCode.USER_REGISTER_FAILED.getCode());
                userRegisterResponse.setMsg(UserRetCode.USER_REGISTER_FAILED.getMessage());
                return userRegisterResponse;
            }

            // 向用户验证表中插入一条记录
            UserVerify userVerify = new UserVerify();
            userVerify.setUsername(member.getUsername());
            // 插入uuid
            String key = member.getUsername() + member.getPassword() + UUID.randomUUID().toString();
            String uuid = DigestUtils.md5DigestAsHex(key.getBytes());
            userVerify.setUuid(uuid);
            userVerify.setRegisterDate(new Date());
            userVerify.setIsExpire("N");
            userVerify.setIsVerify("N");
            effectRows = userVerifyMapper.insert(userVerify);
            if (effectRows != 1) {
                userRegisterResponse.setCode(UserRetCode.USER_REGISTER_VERIFY_FAILED.getCode());
                userRegisterResponse.setMsg(UserRetCode.USER_REGISTER_VERIFY_FAILED.getMessage());
                return userRegisterResponse;
            }

            // 发送用户激活邮件
            sendEmail(uuid, userRegisterRequest);

            // 打印日志
            log.info("用户注册成功，注册参数request:{},{}", JSON.toJSONString(userRegisterRequest), "xxx");
            userRegisterResponse.setCode(UserRetCode.SUCCESS.getCode());
            userRegisterResponse.setMsg(UserRetCode.SUCCESS.getMessage());
            return userRegisterResponse;
        } catch (ValidateException e) {
            ExceptionProcessorUtils.wrapperHandlerException(userRegisterResponse, e);
        }
        return userRegisterResponse;
    }

    /**
     * 用户登录的方法
     *
     * @param userLoginRequest
     * @return
     */
    @Override
    public UserLoginResponse login(UserLoginRequest userLoginRequest) {
        UserLoginResponse userLoginResponse = new UserLoginResponse();
        try {
            // 判断用户名和密码是否为空
            userLoginRequest.requestCheck();

            // password要加密处理
            String md5DigestAsHex = DigestUtils.md5DigestAsHex(userLoginRequest.getPassword().getBytes());

            // 构造查询条件
            // 判断用户名和密码查询用户是否存在
            Example example = new Example(Member.class);
            example.createCriteria()
                    .andEqualTo("username", userLoginRequest.getUserName())
                    .andEqualTo("password", md5DigestAsHex);

            // 查询数据库
            List<Member> memberList = memberMapper.selectByExample(example);
            // 判断用户名和密码是否正确
            if (CollectionUtils.isEmpty(memberList)) {
                throw new ValidateException(UserRetCode.USERORPASSWORD_ERRROR.getCode(), UserRetCode.USERORPASSWORD_ERRROR.getMessage());
            }

            // 判断该用户是否激活
            if ("N".equals(memberList.get(0).getIsVerified())) {
                throw new ValidateException(UserRetCode.USER_ISVERFIED_ERROR.getCode(), UserRetCode.USER_ISVERFIED_ERROR.getMessage());
            }

            // 返回数据
            Member member = memberList.get(0);
            userLoginResponse = userConverterMapper.converter(member);
            // 构造token并放入userLoginResponse中
            HashMap<String, Object> map = new HashMap<>();
            map.put("uid", userLoginResponse.getId());
            map.put("username", userLoginResponse.getUsername());
            String jsonString = JSON.toJSONString(map);
            String token = JwtTokenUtils.builder().msg(jsonString).build().creatJwtToken();
            userLoginResponse.setToken(token);
            // 放入成功标志
            userLoginResponse.setCode(UserRetCode.SUCCESS.getCode());
            userLoginResponse.setMsg(UserRetCode.SUCCESS.getMessage());
            return userLoginResponse;
        } catch (ValidateException e) {
            ExceptionProcessorUtils.wrapperHandlerException(userLoginResponse, e);
        }
        return userLoginResponse;
    }

    /**
     * 验证用户登录的方法
     *
     * @param userLoginVerifyRequest
     * @return
     */
    @Override
    public UserLoginVerifyResponse loginVerify(UserLoginVerifyRequest userLoginVerifyRequest) {
        UserLoginVerifyResponse userLoginVerifyResponse = new UserLoginVerifyResponse();
        try {
            // 构造查询条件
            Example example = new Example(Member.class);
            example.createCriteria()
                    .andEqualTo("id", userLoginVerifyRequest.getUid())
                    .andEqualTo("username", userLoginVerifyRequest.getUsername());
            List<Member> memberList = memberMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(memberList)) {
                throw new ValidateException(UserRetCode.USER_INFOR_INVALID.getCode(), UserRetCode.USER_INFOR_INVALID.getMessage());
            }
            Member member = memberList.get(0);
            userLoginVerifyResponse = userConverterMapper.convertToUserLoginVerifyResponse(member);
            // 放入成功标志
            userLoginVerifyResponse.setCode(UserRetCode.SUCCESS.getCode());
            userLoginVerifyResponse.setMsg(UserRetCode.SUCCESS.getMessage());
            return userLoginVerifyResponse;
        } catch (ValidateException e) {
            ExceptionProcessorUtils.wrapperHandlerException(userLoginVerifyResponse, e);
        }
        return userLoginVerifyResponse;
    }

    /**
     * 用户注册激活的方法
     *
     * @param userVerifyRequest
     * @return
     */
    @Override
    public UserVerifyResponse verify(UserVerifyRequest userVerifyRequest) {
        UserVerifyResponse userVerifyResponse = new UserVerifyResponse();
        try {
            // 判断uuid和username是否为空
            userVerifyRequest.requestCheck();
            // 判断uuid和username是否存在
            Example exampleUserVerify = new Example(UserVerify.class);
            exampleUserVerify.createCriteria()
                    .andEqualTo("uuid", userVerifyRequest.getUuid())
                    .andEqualTo("username", userVerifyRequest.getUserName());
            List<UserVerify> userVerifyList = userVerifyMapper.selectByExample(exampleUserVerify);
            if (CollectionUtils.isEmpty(userVerifyList)) {
                throw new ValidateException(UserRetCode.DATA_NOT_EXIST.getCode(), UserRetCode.DATA_NOT_EXIST.getMessage());
            }

            // 判断该用户是否已经激活
            if ("Y".equals(userVerifyList.get(0).getIsVerify())) {
                throw new ValidateException(UserRetCode.DATA_REPEATED.getCode(), UserRetCode.DATA_REPEATED.getMessage());
            }

            // 用户激活
            UserVerify userVerify = new UserVerify();
            userVerify.setIsVerify("Y");
            userVerifyMapper.updateByExampleSelective(userVerify, exampleUserVerify);
            Example exampleMember = new Example(Member.class);
            Member member = new Member();
            exampleMember.createCriteria()
                    .andEqualTo("username", userVerifyRequest.getUserName());
            member.setIsVerified("Y");
            memberMapper.updateByExampleSelective(member, exampleMember);
            // 返回成功标志
            userVerifyResponse.setCode(UserRetCode.SUCCESS.getCode());
            userVerifyResponse.setMsg(UserRetCode.SUCCESS.getMessage());
            return userVerifyResponse;
        } catch (ValidateException e) {
            ExceptionProcessorUtils.wrapperHandlerException(userVerifyResponse, e);
        }
        return userVerifyResponse;
    }

    /**
     * 发送用户激活邮件
     *
     * @param uuid
     * @param userRegisterRequest
     */
    private void sendEmail(String uuid, UserRegisterRequest userRegisterRequest) {
        SimpleMailMessage message = new SimpleMailMessage();
        message.setSubject(emailProperties.getSubject());
        message.setFrom(emailProperties.getFrom());
        message.setTo(userRegisterRequest.getEmail());
        String replace = emailProperties.getText()
                .replace("username=%s", "username=" + userRegisterRequest.getUserName())
                .replace("uuid=%s", "uuid=" + uuid);
        message.setText(replace);
        mailSender.send(message);
    }

    /**
     * 判断用户名或者密码或者email是否重复的方法
     *
     * @param columnName     数据库中表的字段名
     * @param validParameter 待校验的参数
     */
    private void validRegisterParameterRepeat(String columnName, String validParameter) {
        Example example = new Example(Member.class);
        // 构造查询条件
        example.createCriteria().andEqualTo(columnName, validParameter);
        List<Member> memberList = memberMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(memberList)) {
            throw new ValidateException(UserRetCode.DATA_REPEATED.getCode(), UserRetCode.DATA_REPEATED.getMessage());
        }
    }
}
